#pragma once

#include "QAbstractFile.h"

namespace micro
{

namespace files
{

/**
	Represents a file in memory.
	Automatically grows when necessary.
*/
class  QMemFile : public QAbstractFile
{
protected:
    size_t m_nGrowBy, m_nPos;
    size_t m_nBufSize, m_nDataSize;
    BYTE * m_lpBuf;
    bool m_bAutoDelete;
    void Free()
    {
        if ( m_lpBuf )
        {
            free( m_lpBuf );
            m_lpBuf = nullptr;
        }
    }
    void Init()
    {
        m_nGrowBy = m_nPos = 0;
        m_nBufSize = m_nDataSize = 0;
        m_lpBuf = nullptr;

    }
    void Grow( size_t nBytes );
public:

    QMemFile( long nGrowBy = 1024 )
    {
        Init();
        m_nGrowBy = nGrowBy;
        m_bAutoDelete = true;
    }

    QMemFile( BYTE * lpBuf, UINT nBufSize, long nGrowBy = 0 )
    {
        Init();
        Attach( lpBuf, nBufSize, nGrowBy );
    }

    QMemFile( QMemFile & from )
    {
        Copy( from );
    }

    virtual ~QMemFile()
    {
        Close();
    }

    bool IsClosed() const
    {
        return m_lpBuf == nullptr;
    }
    void Flush() {}

    ULONGLONG Seek( LONGLONG lOff, DWORD nFrom );
    LONGLONG GetFileSize() const
    {
        return m_nDataSize;
    }

    size_t Write( const void * lpBuf, size_t nCount );
    size_t Read( void * lpBuf, size_t nCount );

    void SetFileSize( ULONGLONG nNewLen );


    //QString GetFilePath() const  {return _T("");}




    void Copy( QMemFile & from )
    {
        SetFileSize( from.m_nDataSize );
        from.Read( m_lpBuf, ( DWORD )from.m_nDataSize );
    }

    ULONGLONG GetPosition() const
    {
        return m_nPos;
    }
    void Attach( BYTE * lpBuf, UINT nBufSize, long nGrowBy = 0 )
    {
        Close();
        m_lpBuf = lpBuf;
        m_nGrowBy = nGrowBy;
        m_nBufSize = nBufSize;
        m_nDataSize = nGrowBy == 0 ? nBufSize : 0;
        m_bAutoDelete = false;
    }
    BYTE * Detach()
    {
        BYTE * b = m_lpBuf;
        Init();
        return b;
    }
    void Close()
    {
        if ( m_bAutoDelete )
            Free();

        Init();
    }


};




}

}//micro